#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "Sock.hpp"
#include "Protocol.hpp"
#include "Util.hpp"
#include "log.hpp"
#include "err.hpp"

using namespace std;
using namespace protocol_ns;

static void usage(char *argv)
{
    cout << "Usage:\n\t" << argv << "serverip serverPort" << endl;
}

enum
{
    LEFT,
    OP,
    RIGHT
};

// 格式化输入
Request FormatString(const string &str)
{
    string left, right;
    char op;
    int i = 0;
    int status = LEFT;
    while (i < str.size())
    {
        switch (status)
        {
        case LEFT:
            if (isdigit(str[i]))
                left.push_back(str[i++]);
            else
                status = OP;
            break;
        case OP:
            op = str[i++];
            status = RIGHT;
            break;
        case RIGHT:
            right.push_back(str[i++]);
            break;
        default:
            break;
        }
    }
    Request r;
    r._x = stoi(left);
    r._y = stoi(right);
    r._op = op;

    return r;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    string serverIp = argv[1];
    uint16_t serverPort = atoi(argv[2]);
    string name = "[" + serverIp + ":" + to_string(serverPort) + "]";
    // 创建套接字
    Sock sock;
    sock.Socket();
    // 连接
    int cnt = 5;
    while (sock.Connect(serverIp, serverPort) < 0)
    {
        cout << "正在重连...还有" << --cnt << "次" << endl;
        if (cnt <= 0)
            break;
    }
    if (cnt <= 0)
    {
        logMessage(Fatal, "connect %s error,%s,errno:%d", name.c_str(), strerror(errno), errno);
        exit(CONNECT_ERR);
    }

    // 发送消息
    std::string inbuffer;
    while (true)
    {
        cout << "please enter# ";
        string inStr;
        getline(cin, inStr);
        // 将输入转化成发送的形式
        Request req = FormatString(inStr);
        // 序列化
        string send_string;
        req.Serialize(&send_string);
        send_string = AddHead(send_string);
        // 发数据
        send(sock.Fd(), send_string.c_str(), send_string.size(), 0);

        // 收数据
    START:
        string package;
        int len = ReadPackage(sock.Fd(), inbuffer, &package);
        if (len == 0)
            goto START;
        else if (len == -1)
        {
            logMessage(Warning, "%s quit,me to", name.c_str());
            break;
        }
        else if (len == -2)
        {
            logMessage(Warning, "recv error,%s,errno:%d", strerror(errno), errno);
            break;
        }
        //去报头
        package=RemoveHead(len,package);
        //反序列化
        Responce resp;
        resp.Deserialize(package);

        //输出结果
        cout<<"result:"<<resp._result<<" code:"<<resp._code<<endl;
    }

    sock.Close();

    return 0;
}